package main

/**
接口的3个潜规则
1、对方法的调用限制（接口是一组固定的方法集，由于静态类型的限制，接口变量有时仅能调用其中特定的一些方法）
2、调用函数时的隐式转换（Go语言中的函数调用都是值传递的，变量会在方法调用前进行类型转换）
3、类型断言中的隐式转换
  （类型断言完成后，会返回一个静态类型为你断言的类型的对象，就是说，当使用了类型断言，Go实际上会默认为我们进行一次隐式的类型转换）
*/
import "fmt"

// 接口
type Phone interface {
	call()
}

// 结构体
type iPhone struct {
	name string
}

func (phone iPhone) call() {
	fmt.Println("Hello, iPhone.")
}

func (phone iPhone) send_wechat() {
	fmt.Println("Hello, Wechat.")
}

func printType(i interface{}) {
	switch i.(type) {
	case int:
		fmt.Println("参数的类型是 int")
	case string:
		fmt.Println("参数的类型是 string")
	}
}

func main() {
	//var phone Phone
	//phone = iPhone{name: "周海林的 iphone"}
	//phone.call()
	/**
	如果有 phone.send_wechat(),会报错：phone.send_wechat undefined (type Phone has no field or method send_wechat)
	原因：phone对象显示声明为Phone接口类型，因此phone调用的方法会受到接口的限制。
	*/
	//phone.send_wechat()

	/**
	如何让phone可以调用 send_wechat方法呢？
	1、可以不显示的声明为Phone接口类型，但是要清楚 phone 对象实际上是隐式的实现了Phone接口
	*/
	// 修改后
	phone := iPhone{name: "大海的 iPhone"}
	phone.call()
	phone.send_wechat()
	fmt.Println("=====================================================================")

	a := 10
	printType(a)
	fmt.Println("=====================================================================")

	/**
	将变量b的静态类型转换为interface{}
	*/
	b := 20
	switch interface{}(b).(type) {
	case int:
		fmt.Println("参数的类型是 int")
	case string:
		fmt.Println("参数的类型是 string")
	}

}
